package krao.data;

/**
 * Class for storing data for one class atom of a query, e.g. A(x) or
 * Parent(John).
 * 
 * @author Pepe
 * 
 */
public class ClassAtom extends Atom {
	String firstArgument;

	public ClassAtom(String name, String arg1) {
		super(name);
		firstArgument = getArg(arg1);
	}

	@Override
	public String toString() {
		return String.format("%s(%s)", getName(), firstArgument == null ? "_"
				: firstArgument);
	}

	@Override
	public ClassAtom clone() {
		return new ClassAtom(getName(), firstArgument);
	}

	@Override
	public String getFirstArg() {
		return firstArgument;
	};

	@Override
	public boolean isClassAtom() {
		return true;
	}

	@Override
	public boolean isEmpty() {
		return getFirstArg() == null;
	}

	/**
	 * For two atoms to equal, their names must equal and their parameters must
	 * be either both null, or equal.
	 */
	@Override
	public boolean equals(Object other) {
		if (other == null) {
			return false;
		}
		Atom atom = (Atom) other;
		return atom.isClassAtom()
				&& this.getName().equals(atom.getName())
				&& ((this.getFirstArg() == null && atom.getFirstArg() == null) || (this
						.getFirstArg() != null && this.getFirstArg().equals(
						atom.getFirstArg())));
	}

	/**
	 * Unification means merging two similar atoms. Ex.:
	 * <ul>
	 * <li>A(_) vs A(x) = A(x)</li>
	 * <li>A(_) vs A(_) = P(_)</li>
	 * </ul>
	 * 
	 * @return the result of unification. If these two atoms don't unify (either
	 *         because of different names, different types, or incompatible
	 *         arguments), null is returned.
	 */
	@Override
	public Atom unify(Atom atom) {
		if (atom == null) {
			return null;
		}
		if (atom.isClassAtom() && this.getName().equals(atom.getName())) {
			if (this.getFirstArg() == null) {
				return atom;
			}
			if (atom.getFirstArg() == null) {
				return this;
			}
			if (atom.getFirstArg().equals(this.getFirstArg())) {
				return this;
			}
		}
		return null;
	}

	/**
	 * String used in determining unbound variables. Only variable parameters
	 * are taken into account.
	 * 
	 * @return string in format
	 */
	@Override
	public String getArgString() {
		String first = "";
		if (getFirstArg() != null && getFirstArgVariable()) {
			first = getFirstArg();
		}
		return first;
	}

	@Override
	public boolean getFirstArgVariable() {
		return firstArgument == null ? false : (firstArgument.length() == 1 ? true
				: false);
	};

	@Override
	public int getArgPosition(String argName) {
		if (argName == null) {
			return 0;
		}
		if (argName.equals(this.getFirstArg())) {
			return 1;
		}
		return 0;
	}
}
